#include "Main.h"

VOID my_FinalizeStub(JSContext *cx, JSObject *obj)
{
	JS_GC(cx);
}

INT my_print(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
	for(uintN i = 0; i < argc; i++)
	{
		if(!JSVAL_IS_NULL(argv[i]))
		{
			CHAR *lpszText = JS_GetStringBytes(JS_ValueToString(cx, argv[i]));
			
			PrintText(lpszText);
		}
		else if(JSVAL_IS_OBJECT(argv[i])) {
			jsval tostring;
			// get either the toLocaleString, the toString, or the valueOf function
			JS_GetProperty(cx, obj, "toLocaleString", &tostring);
			if(!(JSVAL_IS_OBJECT(tostring) && JS_ObjectIsFunction(cx, JSVAL_TO_OBJECT(tostring))))
				JS_GetProperty(cx, obj, "toString", &tostring);
			if(!(JSVAL_IS_OBJECT(tostring) && JS_ObjectIsFunction(cx, JSVAL_TO_OBJECT(tostring))))
				JS_GetProperty(cx, obj, "valueOf", &tostring);

			if(JSVAL_IS_OBJECT(tostring) && JS_ObjectIsFunction(cx, JSVAL_TO_OBJECT(tostring)))
			{
				jsval strval;
				JS_CallFunctionValue(cx, obj, tostring, 0, NULL, &strval);
				if(JSVAL_IS_STRING(strval))
					PrintText(JS_GetStringBytes(JSVAL_TO_STRING(strval)));
			}
			else
				PrintText("[object]");
		}
		else PrintText("undefined");
	}

	return JS_TRUE;
}


INT my_delay(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
	if(argc > 0 && JSVAL_IS_INT(argv[0]))
	{
		jsint nDelay = JSVAL_TO_INT(argv[0]);
		SleepEx(nDelay, TRUE);
	}

	return JS_TRUE;
}

INT my_load(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
	if(argc > 0 && JSVAL_IS_STRING(argv[0]))
	{
		ScriptData* js = (ScriptData*)JS_GetContextPrivate(cx);

		if(!js)
			return JS_TRUE;

		CHAR* lpszFileName = JS_GetStringBytes(JS_ValueToString(cx, argv[0]));

		if(!lpszFileName)
			return JS_TRUE;

		if (strlen(lpszFileName) > _MAX_PATH)
			return JS_TRUE;

		CHAR lpszBuf[_MAX_FNAME] = {NULL};
		strcpy(lpszBuf, "scripts\\");
		strcat(lpszBuf,lpszFileName);

		ExecuteScript(lpszBuf, js->IsInGameScript());
	}

	return JS_TRUE;
}

INT my_include(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
	if(argc > 0 && JSVAL_IS_STRING(argv[0]))
	{
		ScriptData* js = (ScriptData*)JS_GetContextPrivate(cx);

		if(!js) 
			return JS_TRUE;

		CHAR * lpszFileName = JS_GetStringBytes(JS_ValueToString(cx, argv[0]));

		if(!lpszFileName)
			return JS_TRUE;

		if(strlen(lpszFileName) <= _MAX_FNAME)
		{

			CHAR lpszBuf[_MAX_PATH+_MAX_FNAME] = {NULL};
			strcpy(lpszBuf, Vars.szPath);
			strcat(lpszBuf, "scripts\\libs\\");
			strcat(lpszBuf, lpszFileName);

			if(js->CheckFileInclude(lpszFileName)) 
			{ 
				*rval = BOOLEAN_TO_JSVAL(TRUE); 
				return JS_TRUE; 
			}

			js->AddFileInclude(lpszFileName);
			jsval tmprval;
			JSScript* tmp = JS_CompileFile(cx, obj, lpszBuf);

			if(tmp) 
			{
				JS_ExecuteScript(cx, obj, tmp, &tmprval);
				JS_DestroyScript(cx, tmp);
				*rval=BOOLEAN_TO_JSVAL(TRUE);
			}
			else 
				*rval=BOOLEAN_TO_JSVAL(FALSE); 
		}
		else
			*rval=BOOLEAN_TO_JSVAL(FALSE);
	}
	else *rval = BOOLEAN_TO_JSVAL(FALSE);

	return JS_TRUE;
}

INT my_stop(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
	if(argc > 0 && (JSVAL_IS_INT(argv[0]) && JSVAL_TO_INT(argv[0]) == 1) ||
				(JSVAL_IS_BOOLEAN(argv[0]) && JSVAL_TO_BOOLEAN(argv[0]) == TRUE))
	{
		ScriptData* js = (ScriptData*)JS_GetContextPrivate(cx);

		if(js)
			js->Stop();

		return JS_FALSE;
	}
	else
	{
		Vars.bAbortScripts = TRUE;
		return JS_FALSE;
	}

	return JS_TRUE;
}

INT my_toDouble(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
	if(argc < 1 || !JSVAL_IS_INT(argv[0]))
		return JS_TRUE;

	JS_NewNumberValue(cx, JSVAL_TO_INT(argv[0]), rval);

	return JS_TRUE;
}


INT my_copyUnit(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
	if(argc < 1 || !JSVAL_IS_OBJECT(argv[0]))
		return JS_TRUE;

	Private* myPrivate = (Private*)JS_GetPrivate(cx, JSVAL_TO_OBJECT(argv[0]));

	if(!myPrivate)
		return JS_TRUE;

	if(myPrivate->dwPrivateType == PRIVATE_UNIT)
	{
		myUnit* lpOldUnit = (myUnit*)JS_GetPrivate(cx, JSVAL_TO_OBJECT(argv[0]));
		myUnit* lpUnit = new myUnit;

		if(!lpUnit)
			return JS_TRUE;

		JSObject* jsunit = JS_NewObject(cx, &unit_class, NULL, NULL);

		if(!jsunit || !JS_DefineProperties(cx, jsunit, unit_props) || !JS_DefineFunctions(cx, jsunit, unit_methods))
		{
			delete lpUnit;
			return JS_TRUE;
		}

		memcpy(lpUnit, lpOldUnit, sizeof(myUnit));
		JS_SetPrivate(cx, jsunit, lpUnit);
		*rval = OBJECT_TO_JSVAL(jsunit);

		return JS_TRUE;
	}
	else if(myPrivate->dwPrivateType == PRIVATE_PLAYER)
	{
		myPlayer* lpOldUnit = (myPlayer*)JS_GetPrivate(cx, JSVAL_TO_OBJECT(argv[0]));
		myPlayer* lpUnit = new myPlayer;

		if(!lpUnit)
			return JS_TRUE;

		JSObject* jsunit = JS_NewObject(cx, &player_class, NULL, NULL);

		if(!jsunit || !JS_DefineProperties(cx, jsunit, player_props) || !JS_DefineFunctions(cx, jsunit, player_methods))
		{
			delete lpUnit;
			return JS_TRUE;
		}

		memcpy(lpUnit, lpOldUnit, sizeof(myPlayer));
		JS_SetPrivate(cx, jsunit, lpUnit);
		*rval = OBJECT_TO_JSVAL(jsunit);

		return JS_TRUE;
	}

	return JS_TRUE;
}

INT my_registerEvent(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
	if(argc < 1 || !JSVAL_IS_INT(argv[0]))
	{
		*rval = BOOLEAN_TO_JSVAL(FALSE);
		return JS_TRUE;
	}

	ScriptData* js = (ScriptData*)JS_GetContextPrivate(cx);

	if(!js) { 
		*rval = BOOLEAN_TO_JSVAL(FALSE); 
		return JS_TRUE; 
	}

	jsint nEvent = JSVAL_TO_INT(argv[0]);

	if(argc == 1)
	{
		if(js->RemoveEvent(nEvent))
			*rval = BOOLEAN_TO_JSVAL(TRUE);
		else *rval = BOOLEAN_TO_JSVAL(FALSE);
	}
	else {
		JSFunction* pFunc = JS_ValueToFunction(cx, argv[1]);
		if(js->RegisterEvent(pFunc, nEvent))
			*rval = BOOLEAN_TO_JSVAL(TRUE);
		else *rval = BOOLEAN_TO_JSVAL(FALSE);
	}

	return JS_TRUE;
}